package com.webbdong.aop.agent.test.bytebuddy;

import net.bytebuddy.asm.Advice;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @program: spring-agent
 * @description:
 * @author: zt22328 赵儒定
 * @create: 2023-03-30 18:07
 **/
public class ExecutorsAdviceInterceptor {

     /**
     * 获取异常，需要添加onThrowable = Throwable.class 和@Advice.Thrown Throwable t，如果没有异常t==null
     */
    @Advice.OnMethodExit
    public static void exit(@Advice.Return Object result){
        System.out.println("------------result>>>>>>>>>>>>>>>>>>>>"+result);
        System.out.println("---[END] ExecutorsAdviceInterceptor");

        try {
            Field fieldTP = ThreadPoolExecutor.class.getDeclaredField("threadPools");
            Map<Object, Object> threadPools = (Map<Object, Object>) fieldTP.get(null);
            if (threadPools != null && threadPools.containsKey(result)){
                return;
            }
            if (result instanceof ThreadPoolExecutor) {
                if (threadPools == null) {
                    synchronized (ThreadPoolExecutor.class) {
                        if (threadPools == null) {
                            threadPools = new ConcurrentHashMap<>();
                            fieldTP.set(null, threadPools);
                        }
                    }
                }

                String threadName = "";
                Method getThreadFactory = result.getClass().getMethod("getThreadFactory");
                Object threadFactory = getThreadFactory.invoke(result);
                Field[] fields = threadFactory.getClass().getDeclaredFields();
                for (Field field : fields) {
                    if (field.getType().equals(String.class) && field.getName().contains("name")) {
                        field.setAccessible(true);
                        threadName = (String) field.get(threadFactory);
                    }
                }
                threadPools.put(result, threadName);
            }
        } catch (Exception e) {

        }
    }
}
